package com.i2works.smartluolong.utils.common;

import com.i2works.smartluolong.utils.base.DateConstant;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.crypto.hash.Md5Hash;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 加解密&字符串处理工具类
 */

public class StrUtil {

    private static Random strGen = new Random();
    private static Random numGen = new Random();
    private static char[] numbersAndLetters = ("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ==").toCharArray();
    private static char[] numbers = ("0123456789").toCharArray();

    public static String md5(String password, String salt) {
        return new Md5Hash(password, salt).toHex();
    }

    /**
     * MD5加密(32位)
     *
     * @param instr 要加密的字符串
     * @return 返回加密后的字符串
     */
    public static String md5(String instr) {
        char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
        try {
            if (StringUtils.isNotBlank(instr)) {
                byte[] strTemp = instr.getBytes();
                // MD5计算方法
                MessageDigest mdTemp = MessageDigest.getInstance("MD5");
                mdTemp.update(strTemp);
                byte[] md = mdTemp.digest();
                int j = md.length;
                char str[] = new char[j * 2];
                int k = 0;
                for (byte byte0 : md) {
                    str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                    str[k++] = hexDigits[byte0 & 0xf];
                }
                return new String(str);
            } else {
                return null;
            }
        } catch (Exception e) {
            return null;
        }
    }


    // md5加密
    public static String md532bit(String inputText) {
        return md5(inputText);
    }


    // md5加密
    @SuppressWarnings("ConstantConditions")
    public static String md516bit(String inputText) {
        return md5(inputText).substring(8, 24);
    }

    // sha加密
    public static String sha40bit(String inputText) {
        return encrypt(inputText, "sha-1");
    }

    /**
     * md5或者sha-1加密
     *
     * @param inputText     要加密的内容
     * @param algorithmName 加密算法名称：md5或者sha-1，不区分大小写
     */
    private static String encrypt(String inputText, String algorithmName) {
        if (inputText == null || "".equals(inputText.trim())) {
            throw new IllegalArgumentException("请输入要加密的内容");
        }
        if (algorithmName == null || "".equals(algorithmName.trim())) {
            algorithmName = "md5";
        }
        try {
            MessageDigest m = MessageDigest.getInstance(algorithmName);
            m.update(inputText.getBytes("UTF8"));
            byte s[] = m.digest();
            // m.digest(inputText.getBytes("UTF8"));
            return hex(s);
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

    // 返回十六进制字符串
    public static String hex(byte[] arr) {
        StringBuilder sb = new StringBuilder();
        for (byte anArr : arr) {
            sb.append(Integer.toHexString((anArr & 0xFF) | 0x100).substring(1, 3));
        }
        return sb.toString();
    }


    /**
     * Base64加密
     */
    public static String encodeBase64(String str) {
        try {
            return Base64.getEncoder().encodeToString(str.trim().getBytes("utf-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return str;
    }

    /**
     * Base64解密
     */
    public static String decodeBase64(String str) {
        try {
            return new String(Base64.getDecoder().decode(str.trim()), "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return str;
    }


    /**
     * 创建密匙
     */
    public static SecretKey createSecretKey(String algorithm) {
        // 声明KeyGenerator对象
        KeyGenerator keygen;
        // 声明 密钥对象
        SecretKey deskey = null;
        try {
            // 返回生成指定算法的秘密密钥的 KeyGenerator 对象
            keygen = KeyGenerator.getInstance(algorithm);
            // 生成一个密钥
            deskey = keygen.generateKey();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        // 返回密匙
        return deskey;
    }

    /**
     * 根据密匙进行DES加密
     */
    public static String encryptToDES(SecretKey key, String info) {
        // 定义 加密算法,可用 DES,DESede,Blowfish
        String Algorithm = "DES";
        // 加密随机数生成器 (RNG),(可以不写)
        SecureRandom sr = new SecureRandom();
        // 定义要生成的密文
        byte[] cipherByte = null;
        try {
            // 得到加密/解密器
            Cipher c1 = Cipher.getInstance(Algorithm);
            // 用指定的密钥和模式初始化Cipher对象
            // 参数:(ENCRYPT_MODE, DECRYPT_MODE, WRAP_MODE,UNWRAP_MODE)
            c1.init(Cipher.ENCRYPT_MODE, key, sr);
            // 对要加密的内容进行编码处理,
            cipherByte = c1.doFinal(info.getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 返回密文的十六进制形式
        return hex(cipherByte);
    }

    /**
     * 根据密匙进行DES解密
     */
    public static String decryptByDES(SecretKey key, String sInfo) {
        // 定义 加密算法,
        String Algorithm = "DES";
        // 加密随机数生成器 (RNG)
        SecureRandom sr = new SecureRandom();
        byte[] cipherByte = null;
        try {
            // 得到加密/解密器
            Cipher c1 = Cipher.getInstance(Algorithm);
            // 用指定的密钥和模式初始化Cipher对象
            c1.init(Cipher.DECRYPT_MODE, key, sr);
            // 对要解密的内容进行编码处理
            cipherByte = c1.doFinal(hex2byte(sInfo));
        } catch (Exception e) {
            e.printStackTrace();
        }
        // return byte2hex(cipherByte);
        return new String(cipherByte);
    }


    /**
     * 十六进制字符串转化为2进制
     */
    public static byte[] hex2byte(String hex) {
        byte[] ret = new byte[8];
        byte[] tmp = hex.getBytes();
        for (int i = 0; i < 8; i++) {
            ret[i] = uniteBytes(tmp[i * 2], tmp[i * 2 + 1]);
        }
        return ret;
    }

    public static byte uniteBytes(byte src0, byte src1) {
        byte aByte = Byte.decode("0x" + new String(new byte[]{src0}));
        aByte = (byte) (aByte << 4);
        byte aByte1 = Byte.decode("0x" + new String(new byte[]{src1}));
        return (byte) (aByte ^ aByte1);
    }

    /**
     * 产生随机字符串 *
     */
    public static String randomStr(int length) {
        if (length < 1) {
            return null;
        }
        char[] randBuffer = new char[length];
        for (int i = 0; i < randBuffer.length; i++) {
            randBuffer[i] = numbersAndLetters[strGen.nextInt(61)];
        }
        return new String(randBuffer);
    }


    /**
     * 产生随机数值字符串 *
     */
    public static String randomInt(int length) {
        if (length < 1) {
            return null;
        }
        char[] randBuffer = new char[length];
        for (int i = 0; i < randBuffer.length; i++) {
            randBuffer[i] = numbers[numGen.nextInt(9)];
        }
        return new String(randBuffer);
    }


    /**
     * 随机数生成
     */
    public static int genRandom(int begin, int end) {
        Random random = new Random();
        return random.nextInt(begin) % (begin - end + 1) + end;
    }

    /**
     * 格式化HTML代码为纯文本
     *
     * @param content
     * @return
     */
    @Deprecated
    public static String html2Txt(String content) {
        // 去除常见html标签和转移符号等
        // 规则：</?[a-zA-Z]*?> 或者 <[^\u4e00-\u9fa5]*?>
        // 除了中文（只包含字母）的任何以<开头的标签
//        content = content.replaceAll("</?[a-zA-Z]*?>|(&[a-zA-Z]*;)", "");
        content = content.replaceAll("<[a-zA-Z/].+>|(&[a-zA-Z]*;)", "");
        // 去除字符串中的空格 回车 换行符 制表符
        content = content.replaceAll("\\s*|\\t|\\r|\\n|\\b|\\r\\n", "");
        // 去除单空格和tab空格
        content = content.replaceAll("　| ", "");
        return content;
    }

    /**
     * byte转换hex
     */
    @Deprecated
    public static String bytesToHex(byte[] bytes) {
        char[] hexChars = new char[bytes.length * 2];
        for (int j = 0; j < bytes.length; j++) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = numbers[v >>> 4];
            hexChars[j * 2 + 1] = numbers[v & 0x0F];
        }
        return new String(hexChars);
    }

    /**
     * bytes转换Str
     */
    public static String bytesToStr(byte[] b) {
        String tmp = "";
        String des = "";
        for (byte aB : b) {
            tmp = Integer.toHexString(aB & 0xFF);
            if (tmp.length() == 1) {
                des += "0";
            }
            des += tmp;
        }
        return des.toUpperCase();
    }


    /**
     * unicode2String
     *
     * @param unicodeStr
     * @return
     */
    public static String unicode2Str(String unicodeStr) {
        StringBuilder sb = new StringBuilder();
        int i = -1;
        int pos = 0;
        if (unicodeStr.contains("\\u")) {
            while ((i = unicodeStr.indexOf("\\u", pos)) != -1) {
                sb.append(unicodeStr.substring(pos, i));
                if (i + 5 < unicodeStr.length()) {
                    pos = i + 6;
                    sb.append((char) Integer.parseInt(unicodeStr.substring(i + 2, i + 6), 16));
                }
            }
            return sb.toString();
        } else {
            return unicodeStr;
        }
    }


    /**
     * string2Unicode
     */
    public static String string2Unicode(String str) {

        StringBuilder unicode = new StringBuilder();
        for (int i = 0; i < str.length(); i++) {
            // 取出每一个字符
            char c = str.charAt(i);
            // 转换为unicode
            unicode.append("\\u" + Integer.toHexString(c));
        }
        return unicode.toString();
    }


    // 将字母转换成数字
    public static void letterToNum(String input) {
        for (byte b : input.getBytes()) {
            System.out.print(b - 96);
        }
    }

    // 将数字转换成字母
    public static void numToLetter(String input) {
        for (byte b : input.getBytes()) {
            System.out.print((char) (b + 48));
        }
    }

    /**
     * 数字倒序
     *
     * @param num
     * @return
     */
    public static int get(int num) {
        String s = String.valueOf(num);
        byte[] by = s.getBytes();
        byte[] by2 = new byte[by.length];
        int t = by.length - 1;
        for (int i = 0; i <= by.length - 1; i++) {
            by2[t] = by[i];
            t--;
        }
        return Integer.parseInt(new String(by2));
    }


    public static <T> Boolean checkInt(T number) {
        //正则判断是否为数字
        String pattern;
        pattern = "^\\d+?$";
        Pattern r = Pattern.compile(pattern, Pattern.MULTILINE);
        Matcher m = r.matcher(String.valueOf(number));
        return m.matches();
    }


    /**
     * 空字符串处理
     */
    public static <T> String strNull(T str) {
        if (str != null) {
            return str.toString();
        }
        return null;
    }

    /**
     * 空数字处理
     *
     * @param number
     * @param <T>
     * @return
     */
    public static <T> Integer intNull(T number) {
        if (number != null) {
            int parseInt = Integer.parseInt(number.toString());
            if (StrUtil.checkInt(parseInt)) {
                return parseInt;
            }
        }
        return 0;
    }

    /**
     * 对字符串中的中文进行编码
     *
     * @param url
     * @return
     */
    public static String chsEncoder(String url) {
        try {
            //中文：[\u4e00-\u9fa5]
            //双字节（中文韩文日文等）：[^\x00-\xff]
            Matcher matcher = Pattern.compile("[^\\x00-\\xff]").matcher(url);
            int count = 0;
            while (matcher.find()) {
                String tmp = matcher.group();
                url = url.replaceAll(tmp, URLEncoder.encode(tmp, "UTF-8"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return url;
    }

    public static String delHTMLTag(String htmlStr) {
        String regEx_script = "<script[^>]*?>[\\s\\S]*?<\\/script>"; //定义script的正则表达式
        String regEx_style = "<style[^>]*?>[\\s\\S]*?<\\/style>"; //定义style的正则表达式
        String regEx_html = "<[^>]+>"; //定义HTML标签的正则表达式
        String regEx_space = "\\s*|\t|\r|\n";//定义空格回车换行符

        Pattern p_script = Pattern.compile(regEx_script, Pattern.CASE_INSENSITIVE);
        Matcher m_script = p_script.matcher(htmlStr);
        htmlStr = m_script.replaceAll(""); //过滤script标签

        Pattern p_style = Pattern.compile(regEx_style, Pattern.CASE_INSENSITIVE);
        Matcher m_style = p_style.matcher(htmlStr);
        htmlStr = m_style.replaceAll(""); //过滤style标签

        Pattern p_html = Pattern.compile(regEx_html, Pattern.CASE_INSENSITIVE);
        Matcher m_html = p_html.matcher(htmlStr);
        htmlStr = m_html.replaceAll(""); //过滤html标签

        Pattern p_space = Pattern.compile(regEx_space, Pattern.CASE_INSENSITIVE);
        Matcher m_space = p_space.matcher(htmlStr);
        htmlStr = m_space.replaceAll(""); //过滤空格回车换行符

        return htmlStr.trim(); //返回文本字符串
    }

    /**
     * 去掉字符串里面的html代码。<br>
     * 要求数据要规范，比如大于小于号要配套,否则会被集体误杀。
     *
     * @paramcontent 　　　　　内容
     * @return去掉后的内容
     */
    public static String stripHtml(String content) {
        //<p>段落替换为换行
        content = content.replaceAll("<p.*?>", "");
        //<br><br/>替换为换行 　
        content = content.replaceAll("<brs*/?>", "");
        //去掉其它的<>之间的东西
        content = content.replaceAll("<.*?>", "");
        //还原HTML//content=HTMLDecoder.decode(content);
        return content;
    }

    public static String replaceHtml(String html) {
        String regEx = "<.+?>"; //表示标签
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(html);
        String s = m.replaceAll("");
        return s;
    }

    /**
     * 泛型转换
     */
    protected static <T> T getValue(String value, Class<T> clazz, T deffault) {
        T ret = null;
        if (deffault instanceof Integer) {
            ret = (clazz.cast(Integer.parseInt(value)));
        } else if (deffault instanceof String) {
            ret = clazz.cast(value);
        } else if (deffault instanceof Double) {
            ret = clazz.cast(Double.parseDouble(value));
        } else if (deffault instanceof Float) {
            ret = clazz.cast(Float.parseFloat(value));
        } else if (deffault instanceof Long) {
            ret = clazz.cast(Long.parseLong(value));
        } else if (deffault instanceof Boolean) {
            ret = clazz.cast(Boolean.parseBoolean(value));
        }
        if (null != ret) {
            return ret;
        }
        return deffault;
    }


    public static String convertFileSize(long size) {
        long kb = 1024;
        long mb = kb * 1024;
        long gb = mb * 1024;

        if (size >= gb) {
            return String.format("%.1fGB", (float) size / gb);
        } else if (size >= mb) {
            float f = (float) size / mb;
            return String.format(f > 100 ? "%.0fMB" : "%.1fMB", f);
        } else if (size >= kb) {
            float f = (float) size / kb;
            return String.format(f > 100 ? "%.0fKB" : "%.1fKB", f);
        } else
            return String.format("%dB", size);
    }

    public static synchronized String getFileName() {
        return DateUtils.get(DateConstant.ALLS_SIMPLE);
    }

}
